<template>
  <dialog ref="dialogRef" class="modal" @close="close">
    <div class="modal-box max-w-[90vw] h-[90vh] flex flex-col relative">
      <form method="dialog">
        <button class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">
          ✕
        </button>
      </form>
      <div class="flex items-center mb-2">
        <h3 class="text-lg font-bold">{{ title }}</h3>

        <!-- 图例 -->
        <div class="flex flex-wrap gap-4 p-3 rounded-xl flex-1">
          <div
            class="flex items-center text-sm p-1 px-2 bg-white rounded-lg shadow-sm"
          >
            <StrongSvg class="text-[#2BA471]" />
            <span>强链</span>
          </div>
          <div
            class="flex items-center text-sm p-1 px-2 bg-white rounded-lg shadow-sm"
          >
            <MissingSvg class="text-[#D54941]" />
            <span>断链</span>
          </div>
          <div
            class="flex items-center text-sm p-1 px-2 bg-white rounded-lg shadow-sm"
          >
            <RecommendSvg class="text-[#4455F2]" />
            <span>招商</span>
          </div>
          <div
            class="flex items-center text-sm p-1 px-2 bg-white rounded-lg shadow-sm"
          >
            <PolicySvg class="text-[#F2AC44]" />
            <span>政策</span>
          </div>
          <div
            class="flex items-center text-sm p-1 px-2 bg-white rounded-lg shadow-sm"
          >
            <div
              class="w-[16px] h-[16px] rounded-md mr-2.5 flex items-center justify-center text-xs shadow-sm bg-white border border-gray-200"
            ></div>
            <span>其他</span>
          </div>
        </div>
      </div>

      <!-- SVG图标定义 -->
      <svg style="display: none">
        <!-- 强链图标 -->
        <symbol id="strong-icon" class="icon" viewBox="0 0 24 24">
          <StrongSvg class="text-[#2BA471] stroke-[#2BA471]" />
        </symbol>

        <!-- 断链图标 -->
        <symbol id="missing-icon" class="icon" viewBox="0 0 24 24">
          <MissingSvg class="text-[#D54941] stroke-[#D54941]" />
        </symbol>

        <!-- 招商图标 -->
        <symbol id="recommend-icon" class="icon" viewBox="0 0 24 24">
          <RecommendSvg class="text-[#4455F2] stroke-[#4455F2]" />
        </symbol>

        <!-- 政策图标 -->
        <symbol id="policy-icon" class="icon" viewBox="0 0 24 24">
          <PolicySvg class="text-[#F2AC44] stroke-[#F2AC44]" />
        </symbol>
      </svg>

      <div
        ref="mermaidRef"
        class="flex-1 h-0 overflow-auto flex justify-center bg-white rounded-xl shadow-sm p-4"
        id="mermaid-diagram"
      ></div>

      <div class="flex gap-2 justify-center mt-4 absolute bottom-8 right-8">
        <button class="btn btn-xs btn-circle" @click="zoomIn">
          <svg
            xmlns="http://www.w3.org/2000/svg"
            width="16"
            height="16"
            fill="currentColor"
            viewBox="0 0 16 16"
          >
            <path
              d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"
            />
          </svg>
        </button>
        <button class="btn btn-xs btn-circle" @click="zoomOut">
          <svg
            xmlns="http://www.w3.org/2000/svg"
            width="16"
            height="16"
            fill="currentColor"
            viewBox="0 0 16 16"
          >
            <path
              d="M4 8a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7A.5.5 0 0 1 4 8z"
            />
          </svg>
        </button>
      </div>
      <!-- tooltip -->
      <div class="bg-[#4455F2] rounded-[12px]" ref="tooltip">
        <div v-if="tooltipOpen">
          <span class="text-white text-sm font-medium px-3 py-2 block pb-0"
            >相关企业</span
          >
          <ul
            class="rounded-box shadow-md p-2 bt-0 w-[200px] max-h-[200px] overflow-y-auto scrollbar-thin"
          >
            <li
              class="items-center border-0 flex justify-between hover:bg-[rgba(255,255,255,0.12)]"
              v-for="(item, index) in requirs"
              :key="index"
            >
              <div
                class="text-white cursor-pointer text-xs pl-2 flex-1 overflow-ellipsis whitespace-nowrap overflow-hidden"
                @click="handleLocationClick(item)"
              >
                {{ item.enterpriseName }}
              </div>
              <LocationIcon class="text-white p-2 box-content cursor-pointer" />
            </li>
            <div
              class="text-white text-center text-xs"
              v-if="requirs.length === 0"
            >
              {{ requirsLoading ? "加载中..." : "暂无数据" }}
            </div>
          </ul>
        </div>
      </div>
    </div>
    <form method="dialog" class="modal-backdrop">
      <button>close</button>
    </form>
  </dialog>
</template>

<script setup>
import { ref, onMounted, onUnmounted, nextTick } from "vue";
import mermaid from "mermaid";
import { mermaidData } from "@/const/mermaid";
import { getRequir } from "@/apis/index.client";
import LocationIcon from "@/assets/images/location-icon.svg";
import { zoom, zoomIdentity } from "d3-zoom";
import { select } from "d3-selection";
import "@/assets/css/mermaid.css";
import PolicySvg from "@/assets/icons/policy.svg";
import StrongSvg from "@/assets/icons/strong.svg";
import MissingSvg from "@/assets/icons/missing.svg";
import RecommendSvg from "@/assets/icons/recommend.svg";

const props = defineProps({
  type: {
    type: Number,
    default: 1,
  },
});
const title = ref("产业链图谱");
const emit = defineEmits(["close"]);
const mermaidRef = ref(null);
const dialogRef = ref(null);
const tooltipOpen = ref(false);
const tooltip = ref(null);
const requirs = ref([]);
const zoomBehavior = ref(null);
const currentZoom = ref(1);
const MIN_ZOOM = 0.1;
const MAX_ZOOM = 5;
const ZOOM_STEP = 0.2;
const requirsLoading = ref(false);

// 使用常量或者props接收的数据
const content = mermaidData[props.type];

const open = () => {
  dialogRef.value.showModal();

  nextTick(() => {
    renderMermaid(content);
  });
};

const close = () => {
  dialogRef.value.close();
  emit("close");
};

const handleLocationClick = (item) => {
  console.log("handleLocationClick", item);

  emit("close");

  // 发布自定义事件，传递位置信息
  $eventBus.emit("locationClick", item);
};

const handleNodeClick = async (node, event) => {
  requirs.value = [];
  const text = node
    .querySelectorAll(".nodeLabel p")?.[0]
    ?.innerHTML.split("<br>")[0]
    .trim();

  if (!text) return;

  const isMiss = node.classList.contains("missing");

  console.log("isMiss", isMiss);

  if (!isMiss) {
    await requestRequir(text);
  }

  const { x, y } = event;
  tooltipOpen.value = true;

  console.log("tooltip", tooltip.value);
  tooltip.value.style.left = `${x - 140}px`;
  tooltip.value.style.top = `${y - 30}px`;
  tooltip.value.style.position = "absolute";
};

// 为节点添加标签 - 从demo.html移植过来
const addTag = (node, className, symbol, offset = 0) => {
  // 创建use元素
  const use = document.createElementNS("http://www.w3.org/2000/svg", "use");

  // 根据className选择对应的图标
  let iconId = "";
  if (className === "tag-strong") {
    iconId = "strong-icon";
  } else if (className === "tag-missing") {
    iconId = "missing-icon";
  } else if (className === "tag-recommend") {
    iconId = "recommend-icon";
  } else if (className === "tag-policy") {
    iconId = "policy-icon";
  }

  use.setAttribute("href", `#${iconId}`);
  use.setAttribute("width", "24");
  use.setAttribute("height", "24");

  const rect = node.querySelector("rect");
  if (rect) {
    use.setAttribute("x", parseInt(rect.getAttribute("x")) - 10 + offset);
    use.setAttribute("y", rect.getAttribute("y") - 10);
  }

  // 将use元素添加到节点中
  node.appendChild(use);
};

// 添加SVG渐变定义 - 从demo.html移植过来
const addSvgDefs = (svg) => {
  const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");

  // 创建渐变
  const gradient = document.createElementNS(
    "http://www.w3.org/2000/svg",
    "linearGradient"
  );
  gradient.setAttribute("id", "cluster-gradient");
  gradient.setAttribute("x1", "0%");
  gradient.setAttribute("y1", "0%");
  gradient.setAttribute("x2", "0%");
  gradient.setAttribute("y2", "100%");

  const stop1 = document.createElementNS("http://www.w3.org/2000/svg", "stop");
  stop1.setAttribute("offset", "0%");
  stop1.setAttribute("stop-color", "#f7f8fc");

  const stop2 = document.createElementNS("http://www.w3.org/2000/svg", "stop");
  stop2.setAttribute("offset", "100%");
  stop2.setAttribute("stop-color", "#f0f2f8");

  gradient.appendChild(stop1);
  gradient.appendChild(stop2);
  defs.appendChild(gradient);

  // 将defs添加到SVG中
  if (svg.firstChild) {
    svg.insertBefore(defs, svg.firstChild);
  } else {
    svg.appendChild(defs);
  }
};

/**
 * 渲染 Mermaid 图表
 * @param {string} content Mermaid 语言的源代码
 */
const renderMermaid = async (content) => {
  if (!mermaidRef.value) return;
  mermaidRef.value.innerHTML = "";
  const id = "mermaid-diagram-" + Date.now();
  try {
    const { svg, bindFunctions } = await mermaid.render(id, content);
    // 直接插入svg
    mermaidRef.value.innerHTML = svg;

    // 绑定事件
    if (bindFunctions) bindFunctions(mermaidRef.value);

    // 为节点添加点击事件和样式
    mermaidRef.value.querySelectorAll(".node").forEach((node) => {
      node.style.cursor = "pointer";

      node.addEventListener("click", (e) => {
        handleNodeClick(node, e);
      });
    });

    // 为节点添加标记标签
    setTimeout(() => {
      // 获取所有节点
      mermaidRef.value.querySelectorAll(".node").forEach((node) => {
        // 检查节点上的类
        const classes = node.classList;
        let offset = 0;

        // 判断是否有各种标签类，并按顺序添加
        if (classes.contains("strong")) {
          addTag(node, "tag-strong", "✓", offset);
          offset += 30; // 每添加一个图标，后续图标向右偏移30px
        }

        if (classes.contains("missing")) {
          addTag(node, "tag-missing", "⚠", offset);
          offset += 30;
        }

        if (classes.contains("recommend")) {
          addTag(node, "tag-recommend", "🎯", offset);
          offset += 30;
        }

        if (classes.contains("policy")) {
          addTag(node, "tag-policy", "📋", offset);
        }
      });

      // 移除原来单独处理特定类的代码，已被上面的通用处理替代
    }, 100);

    // 添加d3缩放功能
    setupZoom();
  } catch (error) {
    console.error("Mermaid 渲染错误:", error);
    mermaidRef.value.innerHTML = "图表渲染失败，请检查语法";
  }
};

// 设置d3缩放功能
const setupZoom = () => {
  if (!mermaidRef.value) return;

  const svg = mermaidRef.value.querySelector("svg");
  if (!svg) return;

  // 获取svg中的主要内容组
  const svgG = svg.querySelector("g");
  if (!svgG) return;

  // 创建zoom行为
  zoomBehavior.value = zoom()
    .scaleExtent([MIN_ZOOM, MAX_ZOOM])
    .on("zoom", (event) => {
      currentZoom.value = event.transform.k;
      svgG.setAttribute("transform", event.transform);
    });

  // 应用zoom行为到svg元素
  select(svg).call(zoomBehavior.value);
};

// 放大功能
const zoomIn = () => {
  if (!mermaidRef.value || !zoomBehavior.value) return;

  const svg = mermaidRef.value.querySelector("svg");
  if (!svg) return;

  const newZoom = Math.min(currentZoom.value + ZOOM_STEP, MAX_ZOOM);

  select(svg)
    .transition()
    .duration(250)
    .call(zoomBehavior.value.transform, zoomIdentity.scale(newZoom));
};

// 缩小功能
const zoomOut = () => {
  if (!mermaidRef.value || !zoomBehavior.value) return;

  const svg = mermaidRef.value.querySelector("svg");
  if (!svg) return;

  const newZoom = Math.max(currentZoom.value - ZOOM_STEP, MIN_ZOOM);

  select(svg)
    .transition()
    .duration(250)
    .call(zoomBehavior.value.transform, zoomIdentity.scale(newZoom));
};

const removeTooltip = () => {
  tooltipOpen.value = false;
};

onMounted(() => {
  mermaid.initialize({
    startOnLoad: false,
    theme: "default",
    securityLevel: "loose",
    fontFamily: "PingFang SC, Microsoft YaHei, sans-serif",
  });
  document.addEventListener("click", removeTooltip, true);
});

onUnmounted(() => {
  // 清除document上的点击事件监听
  document.removeEventListener("click", removeTooltip, true);

  // 清除所有节点上的点击事件
  if (mermaidRef.value) {
    // 移除前检查元素是否存在
    const nodes = mermaidRef.value.querySelectorAll(".node");
    nodes.forEach((node) => {
      // 清除所有点击事件（克隆并替换节点的方式）
      const newNode = node.cloneNode(true);
      if (node.parentNode) {
        node.parentNode.replaceChild(newNode, node);
      }
    });
  }

  // 清除d3-zoom事件
  if (mermaidRef.value) {
    const svg = mermaidRef.value.querySelector("svg");
    if (svg && zoomBehavior.value) {
      select(svg).on(".zoom", null);
    }
  }
});

const requestRequir = async (text) => {
  requirsLoading.value = true;
  getRequir(text)
    .then((res) => {
      console.log(res);
      requirs.value = res;
    })
    .finally(() => {
      requirsLoading.value = false;
    });
};

defineExpose({
  open,
});
</script>

<style scoped>
/* Mermaid需要的特殊样式 - Tailwind难以实现的部分 */
:deep(.mermaid) {
  font-family: "PingFang SC", "Microsoft YaHei", sans-serif !important;
}
:deep(.mermaid .node rect),
:deep(.mermaid .node circle),
:deep(.mermaid .node polygon) {
  filter: drop-shadow(0px 2px 3px rgba(0, 0, 0, 0.1));
}
:deep(.mermaid .edgePath .path) {
  stroke-width: 2px;
  stroke: #ccc;
}
:deep(.mermaid .cluster rect) {
  fill: url(#cluster-gradient) !important;
  stroke: #e5e8f0 !important;
  stroke-width: 1px !important;
  rx: 10px !important;
  ry: 10px !important;
  filter: drop-shadow(0px 2px 3px rgba(0, 0, 0, 0.03));
}
:deep(.mermaid .cluster .label) {
  font-size: 14px;
  font-weight: 500;
  color: #5a6378;
  fill: #5a6378 !important;
}
:deep(.mermaid .edgeLabel) {
  background-color: white !important;
  border-radius: 4px;
}
:deep(.mermaid .label) {
  font-family: "PingFang SC", "Microsoft YaHei", sans-serif !important;
}
:deep(.mermaid foreignObject) {
  overflow: visible;
}

/* 节点标签样式 - 难以用Tailwind实现的部分 */
:deep(.node-tag) {
  position: absolute;
  top: -10px;
  left: -10px;
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  font-size: 12px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
  z-index: 10;
}
:deep(.tag-strong) {
  background-color: #d4f4d1;
  border: 2px solid #2f7d32;
  color: #2f7d32;
}
:deep(.tag-missing) {
  background-color: #ffd6d9;
  border: 2px solid #ff4b4b;
  color: #ff4b4b;
}
:deep(.tag-recommend) {
  background-color: #cdeffa;
  border: 2px solid #0078d4;
  color: #0078d4;
}
:deep(.tag-policy) {
  background-color: #fff4cc;
  border: 2px solid #c29200;
  color: #c29200;
}
</style>
